#include "Socket.h"
#include "Logger.h"
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "InetAddress.h"
#include <cstring>
#include <netinet/tcp.h>  /* for TCP_XXX defines */
namespace mymuduo {

Socket::~Socket() {
    close(socketfd_);
}

void Socket::bindAddress(const InetAddress &localaddr) {
    if(0 != bind(socketfd_, (sockaddr*)localaddr.getSockAddr(), sizeof(sockaddr_in))) {
        LOG_FATAL("bind socketfd:%d fail\n", socketfd_);
    }
}

void Socket::listen() {
    if(0 != ::listen(socketfd_, 1024)) {
        LOG_FATAL("listen socketfd:%d fail\n", socketfd_);
    }
}

int Socket::accept(InetAddress *peeraddr){
    /*
     * accept 参数不合法
     * 对返回的 connfd 没有设置非阻塞
     */
    sockaddr_in addr;
    socklen_t len = sizeof(addr); // 修改
    bzero(&addr, sizeof(addr));
    int connfd = ::accept4(socketfd_, (sockaddr*)&addr, &len, SOCK_NONBLOCK | SOCK_CLOEXEC); // 修改
    if(connfd >= 0) {
        peeraddr->setSocketAddr(addr);
    }
    return connfd;
}

void Socket::shutdownWrite() {
    if(::shutdown(socketfd_, SHUT_WR) < 0) {
        LOG_ERROR("Socket::shutdownWrite error\n");
    }
}

void Socket::setTcpNoDelay(bool on) {
    int optval = on ? 1 : 0;
    ::setsockopt(socketfd_, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
}

void Socket::setReuseAddr(bool on) {
    int optval = on ? 1 : 0;
    ::setsockopt(socketfd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
}

void Socket::setReusePort(bool on) {
    int optval = on ? 1 : 0;
    ::setsockopt(socketfd_, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
}

void Socket::setKeepAlive(bool on) {
    int optval = on ? 1 : 0;
    ::setsockopt(socketfd_, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
}

}
